import './style/index.less';
import { useEffect, useMemo, useState } from 'react';
const holders = [
  'top-left',
  'top-center',
  'top-right',
  'bottom-left',
  'bottom-center',
  'bottom-right',
  'left-center',
  'right-center',
];

const defaultOffset = {
  width: 0,
  height: 0,
  top: 0,
  left: 0,
};

const Dragger = props => {
  const {
    children,
    defaultValue,
    value,
    onChange,
    minWidth = 0,
    minHeight = 0,
  } = props;
  const [draggerJson, setDraggerJson] = useState({ move: false });

  const [offset, setOffset] = useState(
    typeof defaultValue === 'function'
      ? defaultValue()
      : defaultValue || defaultOffset
  );

  useEffect(() => {
    if (value != null) {
      setOffset(prev => ({ ...prev, ...value }));
    }
  }, [value]);

  const styles = useMemo(() => {
    const { top, left, width, height } = offset || {};
    const wrapper = {
      transform: `translate(${left}px, ${top}px)`,
      width: `${width}px`,
      height: `${height}px`,
    };
    return {
      wrapper,
    };
  }, [offset]);

  const onMouseDown = (event, type) => {
    // 取消鼠标右键单击
    if (event.ctrlKey || event.button === 2) {
      return;
    }
    const { clientX: startX, clientY: startY } = event;
    const {
      top: prevTop,
      left: prevLeft,
      width: prevWidth,
      height: prevHeight,
    } = offset;
    const memoOffset = { ...offset };
    setDraggerJson(prev => ({ ...prev, move: true }));

    const onMouseMove = e => {
      e.stopPropagation();
      e.preventDefault();
      const { clientY, clientX } = e;
      const newDraggerJson = {};
      switch (type) {
        case 'center': {
          newDraggerJson.left = prevLeft + clientX - startX;
          newDraggerJson.top = prevTop + clientY - startY;
          break;
        }
        case 'top-center': {
          newDraggerJson.height = Math.max(
            prevHeight - (clientY - startY),
            minHeight
          );
          if (newDraggerJson.height > minHeight) {
            newDraggerJson.top = prevTop + (clientY - startY);
          }
          break;
        }
        case 'bottom-center': {
          newDraggerJson.height = prevHeight + clientY - startY;
          break;
        }
        case 'left-center': {
          newDraggerJson.width = Math.max(
            prevWidth - (clientX - startX),
            minWidth
          );
          if (newDraggerJson.width > minWidth) {
            newDraggerJson.left = prevLeft + (clientX - startX);
          }
          break;
        }
        case 'right-center': {
          newDraggerJson.width = prevWidth + clientX - startX;
          break;
        }
        case 'bottom-right': {
          newDraggerJson.width = prevWidth + clientX - startX;
          newDraggerJson.height = prevHeight + clientY - startY;
          break;
        }
        case 'bottom-left': {
          newDraggerJson.width = Math.max(
            prevWidth - (clientX - startX),
            minWidth
          );
          newDraggerJson.height = Math.max(
            prevHeight + clientY - startY,
            minHeight
          );
          if (newDraggerJson.width > minWidth) {
            newDraggerJson.left = prevLeft + (clientX - startX);
          }
          break;
        }
        case 'top-left': {
          newDraggerJson.width = Math.max(
            prevWidth - (clientX - startX),
            minWidth
          );
          newDraggerJson.height = Math.max(
            prevHeight - (clientY - startY),
            minHeight
          );
          if (newDraggerJson.width > minWidth) {
            newDraggerJson.left = prevLeft + (clientX - startX);
          }
          if (newDraggerJson.height > minHeight) {
            newDraggerJson.top = prevTop + (clientY - startY);
          }
          break;
        }
        case 'top-right': {
          newDraggerJson.width = prevWidth + (clientX - startX);
          newDraggerJson.height = Math.max(
            prevHeight - (clientY - startY),
            minHeight
          );
          if (newDraggerJson.height > minHeight) {
            newDraggerJson.top = prevTop + (clientY - startY);
          }
          break;
        }
        default:
          break;
      }
      setOffset(prev => ({ ...prev, ...newDraggerJson }));
      Object.assign(memoOffset, newDraggerJson);
    };
    const onMouseUp = e => {
      setDraggerJson(prev => ({ ...prev, move: false }));
      onChange(memoOffset);
      document.removeEventListener('mousemove', onMouseMove);
      document.removeEventListener('mouseup', onMouseUp);
    };
    document.addEventListener('mousemove', onMouseMove);
    document.addEventListener('mouseup', onMouseUp);
  };
  return (
    <div
      className={`ski-dragger ${draggerJson.move ? 'move' : ''}`}
      style={styles.wrapper}
    >
      <div className="ski-dragger-dotted left"></div>
      <div className="ski-dragger-dotted top"></div>
      <div className="ski-dragger-dotted bottom"></div>
      <div className="ski-dragger-dotted right"></div>
      {holders.map(holder => {
        return (
          <div
            className={`ski-dragger-holder ${holder}`}
            key={holder}
            onMouseDown={e => onMouseDown(e, holder)}
          ></div>
        );
      })}
      <div
        className="ski-dragger-body"
        onMouseDown={e => onMouseDown(e, 'center')}
      >
        {children}
      </div>
    </div>
  );
};

export default Dragger;
